package com.corner.model.leancloud.helper;

import android.support.annotation.NonNull;
import android.text.TextUtils;

import com.alibaba.sdk.android.oss.model.OSSException;
import com.avos.avoscloud.im.v2.AVIMConversation;
import com.avos.avoscloud.im.v2.AVIMException;
import com.avos.avoscloud.im.v2.callback.AVIMConversationCallback;
import com.avos.avoscloud.im.v2.messages.AVIMTextMessage;
import com.corner.R;
import com.corner.app.App;
import com.corner.model.cornerservice.domain.CloudFile;
import com.corner.model.cornerservice.domain.User;
import com.corner.model.cornerservice.service.exception.BaseException;
import com.corner.model.db.DBConstans;
import com.corner.model.db.Session;
import com.corner.model.oss.OSSManager;
import com.corner.utils.AudioUtil;
import com.corner.utils.ToastUtil;

import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * Created by Administrator on 2015/5/12.
 */
public class MessageHelperV2 extends BaseMessageHelper {


    @NonNull
    private static Session getInitSession(String friendId) {
        final Session session = new Session();
        session.setToUserId(friendId);
        session.setFromUserId(User.getCurrentUser().getObjectId().toString());
        session.setIsReaded(true);
        setSessionState(session);
        session.setSessionId(UUID.randomUUID().toString());
        session.setSessionName(friendId);
        session.setTimestamp(new Date());
        return session;
    }


    public static void addToBlackList(final String friendId, final AddToBlackCallBack callBack) {
        getAvImConversationNotInBlackList(friendId, new OnGetConversation() {
            @Override
            public void onGet(AVIMConversation conversation) {
                if (null != conversation) {
                    HashMap<String, Object> params = new HashMap<String, Object>();
                    params.put(DBConstans.TYPE, DBConstans.BLACK_LIST);
                    AVIMTextMessage textMessage = new AVIMTextMessage();
                    textMessage.setAttrs(params);
                    conversation.sendMessage(textMessage, new AVIMConversationCallback() {
                        @Override
                        public void done(AVIMException e) {
                            if (e == null) {
                                callBack.onGetResult(true);
                            } else {
                                ToastUtil.showCustomToastInDevelop(App.application, e.getMessage());
                                callBack.onGetResult(false);
                            }
                        }
                    });
                } else {
                    callBack.onGetResult(false);
                    ToastUtil.showCustomToastInDevelop(App.application, App.application.getString(R.string.exception_coversation_null));
                }
            }
        });
    }

    /**
     * 发送comment
     *
     * @param text
     * @param infoId
     * @param friendId
     */
    public static void sendComment(final String text, final Long infoId, final String friendId) {
        Observable.create(new Observable.OnSubscribe<Session>() {
            @Override
            public void call(Subscriber<? super Session> subscriber) {
                final Session session = getInitSession(friendId);
                session.setType(DBConstans.COMMENT);
                session.setInfoId(infoId);
                session.setText(text);
                App.application.daoSession.getSessionDao().insert(session);
                subscriber.onNext(session);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Session>() {
            @Override
            public void call(Session session) {
                sendComment(session);
            }
        });
    }



    /**
     * 发送数据库已经存在的Comment
     *
     * @param session
     */
    private static void sendComment(final Session session) {
        getAvImConversationNotInBlackList(session.getToUserId(), new OnGetConversation() {
            @Override
            public void onGet(AVIMConversation conversation) {
                if (null != conversation) {
                    HashMap<String, Object> params = new HashMap<String, Object>();
                    params.put(DBConstans.SESSION_ID,session.getSessionId());
                    params.put(DBConstans.INFOID, session.getInfoId());
                    params.put(DBConstans.TYPE, DBConstans.COMMENT);
                    AVIMTextMessage textMessage = new AVIMTextMessage();
                    textMessage.setText(session.getText());
                    textMessage.setAttrs(params);
                    conversation.sendMessage(textMessage, getAVIMConversationCallback(session,textMessage));
                } else {
                    sendMessageFailed(session);
                    ToastUtil.showCustomToastInDevelop(App.application, App.application.getString(R.string.exception_coversation_null));
                }
            }
        });
    }

    /**
     * 分享
     *
     * @param text
     * @param locationId
     * @param friendId
     */
    public static void sendShare(final String text, final Long locationId, final String friendId) {
        Observable.create(new Observable.OnSubscribe<Session>() {
            @Override
            public void call(Subscriber<? super Session> subscriber) {
                Session session = getInitSession(friendId);
                session.setText(text);
                session.setType(DBConstans.SHARE);
                session.setLocationId(locationId);

                App.application.daoSession.getSessionDao().insert(session);
                subscriber.onNext(session);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Session>() {
            @Override
            public void call(Session session) {
                sendShare(session);
            }
        });
    }



    /**
     * 发送数据库已经存在的Share
     *
     * @param session
     */
    private static void sendShare(final Session session) {
        getAvImConversationNotInBlackList(session.getToUserId(), new OnGetConversation() {
            @Override
            public void onGet(AVIMConversation conversation) {
                if (null != conversation) {
                    HashMap<String, Object> params = new HashMap<String, Object>();
                    params.put(DBConstans.SESSION_ID,session.getSessionId());
                    params.put(DBConstans.LOCATION_ID, session.getLocationId());
                    params.put(DBConstans.TYPE, DBConstans.SHARE);
                    AVIMTextMessage textMessage = new AVIMTextMessage();
                    textMessage.setText(session.getText());
                    textMessage.setAttrs(params);
                    conversation.sendMessage(textMessage, getAVIMConversationCallback(session,textMessage));
                } else {
                    sendMessageFailed(session);
                    ToastUtil.showCustomToastInDevelop(App.application, App.application.getString(R.string.exception_coversation_null));
                }
            }
        });
    }



    /**
     * 发送文本
     *
     * @param text
     * @param friendId
     */
    public static void sendText(final String text, final String friendId) {

        Observable.create(new Observable.OnSubscribe<Session>() {
            @Override
            public void call(Subscriber<? super Session> subscriber) {
                final Session session = getInitSession(friendId);
                session.setText(text);
                session.setType(DBConstans.TEXT);
                App.application.daoSession.getSessionDao().insert(session);
                subscriber.onNext(session);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Session>() {
            @Override
            public void call(Session session) {
                sendText(session);
            }
        });
    }

    /**
     * 发送数据库已经存在的文本
     *
     * @param session
     */
    private static void sendText(final Session session) {
        getAvImConversationNotInBlackList(session.getToUserId(), new OnGetConversation() {
            @Override
            public void onGet(AVIMConversation conversation) {
                if (null != conversation) {
                    HashMap<String, Object> params = new HashMap<String, Object>();
                    params.put(DBConstans.SESSION_ID,session.getSessionId());
                    params.put(DBConstans.TYPE, DBConstans.TEXT);
                    AVIMTextMessage textMessage = new AVIMTextMessage();
                    textMessage.setText(session.getText());
                    textMessage.setAttrs(params);
                    conversation.sendMessage(textMessage, getAVIMConversationCallback(session, textMessage));
                } else {
                    sendMessageFailed(session);
                    ToastUtil.showCustomToastInDevelop(App.application, App.application.getString(R.string.exception_coversation_null));
                }
            }
        });
    }


    /**
     * 发送图片
     *
     * @param path
     * @param friendId
     */
    public static void sendPic(final String path, final String friendId) {

        Observable.create(new Observable.OnSubscribe<Session>() {
            @Override
            public void call(Subscriber<? super Session> subscriber) {
                final Session session = getInitSession(friendId);
                session.setPicPath(path);
                session.setType(DBConstans.PIC);
                App.application.daoSession.getSessionDao().insert(session);
                subscriber.onNext(session);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Session>() {
            @Override
            public void call(Session session) {
                sendPic(session);
            }
        });
    }

    /**
     * 发送数据库已经存在的图片
     *
     * @param session
     */
    private static void sendPic(final Session session) {
        getAvImConversationNotInBlackList(session.getToUserId(), new OnGetConversation() {
            @Override
            public void onGet(final AVIMConversation conversation) {
                //上传Pic,生成AVIMTextMessage
                Observable.create(new Observable.OnSubscribe<AVIMTextMessage>() {
                    @Override
                    public void call(Subscriber<? super AVIMTextMessage> subscriber) {
                        if (null != conversation) {
                            try {
                                final HashMap<String, Object> params = new HashMap<String, Object>();
                                if (!TextUtils.isEmpty(session.getPicPath())) {
                                    CloudFile upload = OSSManager.upload(session.getPicPath());
                                    params.put(DBConstans.PIC, upload.getFileUrl());
                                    session.setPic(upload.getFileUrl());
                                }
                                params.put(DBConstans.SESSION_ID,session.getSessionId());
                                params.put(DBConstans.TYPE, DBConstans.PIC);
                                App.application.daoSession.getSessionDao().update(session);
                                AVIMTextMessage message = new AVIMTextMessage();
                                message.setAttrs(params);
                                subscriber.onNext(message);
                            } catch (FileNotFoundException | BaseException | OSSException e) {
                                e.printStackTrace();
                                subscriber.onError(e);
                            }
                        } else {
                            subscriber.onError(new Throwable(App.application.getString(R.string.exception_coversation_null)));
                        }
                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<AVIMTextMessage>() {
                    @Override
                    public void call(AVIMTextMessage avimTextMessage) {
                        conversation.sendMessage(avimTextMessage, getAVIMConversationCallback(session,avimTextMessage));
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        sendMessageFailed(session);
                        ToastUtil.showCustomToastInDevelop(App.application, throwable.getMessage());
                    }
                });
            }
        });
    }

    /**
     * 发送语音
     *
     * @param path
     * @param friendId
     */
    public static void sendAudio(final String path, final String friendId) {
        final Session session = getInitSession(friendId);
        Observable.create(new Observable.OnSubscribe<Session>() {
            @Override
            public void call(Subscriber<? super Session> subscriber) {
                try {
                    session.setAudioDuration(String.valueOf(AudioUtil.getAmrDuration(path)));
                    session.setType(DBConstans.AUDIO);
                    session.setAudioPath(path);
                    App.application.daoSession.getSessionDao().insert(session);
                    subscriber.onNext(session);
                } catch (IOException e) {
                    e.printStackTrace();
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Session>() {
            @Override
            public void call(Session session) {
                sendAudio(session);
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                ToastUtil.showCustomToastInDevelop(App.application, throwable.getMessage());
                sendMessageFailed(session);
            }
        });
    }

    /**
     * 发送数据库已经存在的Audio
     *
     * @param session
     */
    private static void sendAudio(final Session session) {
        getAvImConversationNotInBlackList(session.getToUserId(), new OnGetConversation() {
            @Override
            public void onGet(final AVIMConversation conversation) {
                Observable.create(new Observable.OnSubscribe<AVIMTextMessage>() {
                    @Override
                    public void call(Subscriber<? super AVIMTextMessage> subscriber) {
                        if (null != conversation) {
                            try {
                                final HashMap<String, Object> params = new HashMap<String, Object>();
                                if (!TextUtils.isEmpty(session.getAudioPath())) {
                                    CloudFile upload = OSSManager.upload(session.getAudioPath());
                                    params.put(DBConstans.AUDIO, upload.getFileUrl());
                                    session.setAudio(upload.getFileUrl());
                                }
                                params.put(DBConstans.SESSION_ID,session.getSessionId());
                                params.put(DBConstans.TYPE, DBConstans.AUDIO);
                                params.put(DBConstans.AUDIODURATION, session.getAudioDuration());
                                App.application.daoSession.getSessionDao().update(session);
                                AVIMTextMessage message = new AVIMTextMessage();
                                message.setAttrs(params);
                                subscriber.onNext(message);
                            } catch (FileNotFoundException | BaseException | OSSException e) {
                                e.printStackTrace();
                                subscriber.onError(e);
                            }
                        } else {
                            subscriber.onError(new Throwable(App.application.getString(R.string.exception_coversation_null)));
                        }
                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<AVIMTextMessage>() {
                    @Override
                    public void call(AVIMTextMessage message) {
                        conversation.sendMessage(message, getAVIMConversationCallback(session,message));
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        sendMessageFailed(session);
                        ToastUtil.showCustomToastInDevelop(App.application, throwable.getMessage());
                    }
                });
            }
        });
    }





    /**
     * 发送语音表情
     *
     * @param picPath
     * @param audioPath
     * @param friendId
     */
    public static void sendPicAudio(final String picPath, final String audioPath, final String friendId) {
        Observable.create(new Observable.OnSubscribe<Session>() {
            @Override
            public void call(Subscriber<? super Session> subscriber) {
               Session session = getInitSession(friendId);
                try {
                    session.setType(DBConstans.PIC_AUDIO);
                    session.setAudioPath(audioPath);
                    session.setPicPath(picPath);
                    session.setAudioDuration(String.valueOf(AudioUtil.getAmrDuration(audioPath)));

                    App.application.daoSession.getSessionDao().insert(session);
                    subscriber.onNext(session);
                } catch (IOException e) {
                    e.printStackTrace();
                    session.setIsSent(DBConstans.SENT_FAILED);
                    App.application.daoSession.getSessionDao().insert(session);
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Session>() {
            @Override
            public void call(Session session) {
                sendPicAudio(session);
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                //do nothing
                ToastUtil.showCustomToastInDevelop(App.application, App.application.getString(R.string.exception_coversation_null));
            }
        });
    }

    /**
     * 发送已经存在于数据库中语音表情
     *
     * @param session
     */
    private static void sendPicAudio(final Session session) {
        getAvImConversationNotInBlackList(session.getToUserId(), new OnGetConversation() {
            @Override
            public void onGet(final AVIMConversation conversation) {
                if (null != conversation) {
                    Observable.create(new Observable.OnSubscribe<AVIMTextMessage>() {
                        @Override
                        public void call(Subscriber<? super AVIMTextMessage> subscriber) {
                            try {
                                final HashMap<String, Object> params = new HashMap<String, Object>();
                                if (!TextUtils.isEmpty(session.getPicPath())) {
                                    CloudFile upload = OSSManager.upload(session.getPicPath());
                                    params.put(DBConstans.PIC, upload.getFileUrl());
                                    session.setPic(upload.getFileUrl());
                                }
                                if (!TextUtils.isEmpty(session.getAudioPath())) {
                                    CloudFile upload = OSSManager.upload(session.getAudioPath());
                                    params.put(DBConstans.AUDIO, upload.getFileUrl());
                                    session.setAudio(upload.getFileUrl());
                                }
                                params.put(DBConstans.SESSION_ID,session.getSessionId());
                                params.put(DBConstans.TYPE, DBConstans.PIC_AUDIO);
                                params.put(DBConstans.AUDIODURATION, session.getAudioDuration());

                                App.application.daoSession.getSessionDao().update(session);
                                AVIMTextMessage message = new AVIMTextMessage();
                                message.setAttrs(params);
                                subscriber.onNext(message);
                            } catch (IOException | BaseException | OSSException e) {
                                e.printStackTrace();
                                subscriber.onError(e);
                            }
                        }
                    }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<AVIMTextMessage>() {
                        @Override
                        public void call(AVIMTextMessage avimTextMessage) {
                            conversation.sendMessage(avimTextMessage, getAVIMConversationCallback(session,avimTextMessage));
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            sendMessageFailed(session);
                            ToastUtil.showCustomToastInDevelop(App.application, throwable.getMessage());
                        }
                    });
                } else {
                    sendMessageFailed(session);
                    ToastUtil.showCustomToastInDevelop(App.application, App.application.getString(R.string.exception_coversation_null));
                }
            }
        });
    }

    /**
     * 设置session的发送状态
     *
     * @param session
     */
    private static void setSessionState(Session session) {

//        if (!ChatEventHanlder.isConnected) {
//            session.isSent = DomainConstans.SENT_FAILED;
//        } else {
        session.setIsSent(DBConstans.SENTING);
//        }
    }

    /**
     * 发送消息成功
     * @param session
     * @param message
     */
    private static void sendMessageSucess(final Session session, final AVIMTextMessage message) {
        Observable.create(new Observable.OnSubscribe<Object>() {
            @Override
            public void call(Subscriber<? super Object> subscriber) {
                session.setIsSent(DBConstans.SENT);
                if (message!=null) {
                    session.setMessageId(message.getMessageId());
                }
                App.application.daoSession.getSessionDao().update(session);
            }
        }).subscribeOn(Schedulers.io()).subscribe();
    }
    /**
     * 发送消息失败
     * @param session
     */
    private static void sendMessageFailed(final Session session) {
        Observable.create(new Observable.OnSubscribe<Object>() {
            @Override
            public void call(Subscriber<? super Object> subscriber) {
                session.setIsSent(DBConstans.SENT_FAILED);
                App.application.daoSession.getSessionDao().update(session);
            }
        }).subscribeOn(Schedulers.io()).subscribe();
    }

    @NonNull
    private static AVIMConversationCallback getAVIMConversationCallback(final Session session, final AVIMTextMessage message) {
        final Subscription subscribe = Observable.timer(20, TimeUnit.SECONDS, Schedulers.immediate()).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {
                        ToastUtil.showCustomToastInDevelop(App.application, "消息发送超时");
                        sendMessageFailed(session);
                    }
                });
        AVIMConversationCallback callback = new AVIMConversationCallback() {
            @Override
            public void done(AVIMException e) {
                subscribe.unsubscribe();
                if (e == null) {
                    sendMessageSucess(session, message);
                } else {
                    ToastUtil.showCustomToastInDevelop(App.application, e.getMessage());
                    sendMessageFailed(session);
                }
            }
        };
        return callback;
    }

    /**
     * 重新发送
     *
     * @param session
     */
    public static void resend(final Session session) {
        Observable.create(new Observable.OnSubscribe<Session>() {
            @Override
            public void call(Subscriber<? super Session> subscriber) {
                setSessionState(session);
                session.setTimestamp(new Date());
                App.application.daoSession.getSessionDao().update(session);
                subscriber.onNext(session);
            }
        }).subscribeOn(Schedulers.io()).subscribe(new Action1<Session>() {
            @Override
            public void call(Session session) {
                if (session.getType().equals(DBConstans.TEXT)) {
                    sendText(session);
                } else if (session.getType().equals(DBConstans.AUDIO)) {
                    if (new File(session.getAudioPath()).exists()) {
                        sendAudio(session);
                    } else {
                        sendMessageFailed(session);
                    }
                } else if (session.getType().equals(DBConstans.COMMENT)) {
                    sendComment(session);
                } else if (session.getType().equals(DBConstans.SHARE)) {
                    sendShare(session);
                } else if (session.getType().equals(DBConstans.PIC_AUDIO)) {
                    if (new File(session.getAudioPath()).exists() && new File(session.getPicPath()).exists()) {
                        sendPicAudio(session);
                    } else {
                        sendMessageFailed(session);
                    }
                } else if (session.getType().equals(DBConstans.PIC)) {
                    if (new File(session.getPicPath()).exists()) {
                        sendPic(session);
                    } else {
                        sendMessageFailed(session);
                    }
                }
            }
        });
    }



    /**
     * 加入黑名单的回调
     */
    public interface AddToBlackCallBack {
        void onGetResult(Boolean isSucess);
    }
}
